#ifndef QKNXSERIAL_H
#define QKNXSERIAL_H

#include <QtSerialPort/QSerialPort>

#define COM_BUFF_LEN 1600  //串口接收缓冲区的大小
#define WAIT_WRITE_TIME  300  //串口等待发送完成的时间300ms
#define READ_WAIT_TIME  300  //串口等待读取的最大时间300ms
#define WAIT_READ_TIME  300  //串口读取等待延时300ms
#define DEVICE_TYPE_NUM  4  //设备型号的数量
#define MAX_STANDMESSAGE_LEN  23  //标准帧的最大报文长度
#define MAX_STAND_COMMESSAGE_LEN  29  //标准帧串口报文长度（加报文头）
#define MAX_MESSAGE_NUM  10  //最大支持的报文存储数量

//knx报文解析数据存储结构体
typedef struct knxMess
{
    uchar flag;
    QString priority;
    QString sourceAddr;
    QString destAddr;
    uchar route;
    QString messageType;
    QString DPT;
    QString info;
    QString iack;
}tknxMess;

//实用数据信息等相关数据存储结构体
typedef struct knxMessInfo
{
    QString messageType;
    QString messageDPT;
    QString messageInfo;
}tMessageInfo;

//形成的knx报文存储结构体
typedef struct packStandKnxMess
{
    uchar messageLen;
    uchar message[MAX_STANDMESSAGE_LEN];
}tSPMess;

//串口收发缓存uchar数组(串口接收到的数据中可能包含多条有效报文，需要自行处理)
typedef struct readWriteArray
{
    uchar arrayLen[MAX_MESSAGE_NUM];
    uchar arrayNum;
    uchar message[COM_BUFF_LEN];
}tRDWRBUFF;

//将跟knx协议或者Qt5serial串口类有关部分的函数封装到该QknxSerial类中
class QknxSerial
{
public:
    QknxSerial();
    
    ~QknxSerial();
    
    //进行简单报文过滤
    tRDWRBUFF* knxPacketFilter(tRDWRBUFF* message);
    
    //获取串口接收到的数据
    tRDWRBUFF* knxGetReadComData(QSerialPort* serial,tRDWRBUFF* readComBuff);

    //获取校验字节函数
    unsigned char knxGetFramecheck(unsigned char* message,int messageLen);
    
    //增加报文头
    unsigned char* knxAddMessageHeader(unsigned char* messageNew,unsigned char* messageOld,int messageLen);
    
    //进行报文头和校验字节校验函数
    int knxJudgeMessageHeadAndFramecheck(unsigned char* message);
    
    //发送5个字节的反馈报文的函数
    void knxSendFeedbackMessage(QSerialPort *serial,int sendFlag);
    
    //等待接收串口信息的函数
    QByteArray knxWaitReadSerial(QSerialPort *serial);
    
    //判断5个字节的反馈报文的函数
    int knxJudgeFeedbackMessage(int readLen);
    
    //判断写数据后的14个字节的回复报文的函数
    int knxJudgeMemoryWriteRespone(int readLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow);
    
    //重发函数（预留）
    QByteArray knxResend(QSerialPort *serial,unsigned char* message,int messageLen);
    
    //计算设备序列号报文的函数
    unsigned char* knxGetSNMessage(unsigned char* SNSendMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,unsigned char propertyID,unsigned char deviceTypeByteHigh,unsigned char deviceTypeByteLow);
    
    //获取报文类型、实用数据信息等
    tMessageInfo* knxGetMessageTypeAndDataInfo(uchar* message,int messageLen,tMessageInfo* tInfo);
    
    //解析报文并获取返回解析后的数据
    tknxMess* knxunPackStandMessage(unsigned char* comMessage,int messageLen,tknxMess* standMessageUnpackRes);
    
    //形成knx报文的函数（目前使用TP1报文格式且最大支持四个字节的数据处理）
    tSPMess* knxPackStandMessage(uchar isMessageRepeat,uchar priority,QString sourceAddr,bool destAddrType,QString destAddr,uchar route,uchar dataType,ushort commandType,QString data,tSPMess* packMessage);
    
    //计算数据字节（仅支持TP1报文且最大字节数暂为4）
    uchar* knxGetDataArray(uchar dataType,ushort commandData,QString data,uchar* dataArray);
    
    //获取设备序列号的函数
    int knxSearchDeviceSN(QSerialPort* serial,unsigned char* SNSendMessage,int SNSendMessageLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char snBuff[][6],unsigned char propertyID);
    
    //计算写设备物理地址的广播帧报文
    unsigned char* knxGetWritePAByBroadcastMethod(unsigned char* writeDevicePAMessage, unsigned char MCPAByteHigh, unsigned char MCPAByteLow, unsigned char newPAByteHigh, unsigned char newPAByteLow);
    
    //通过广播方式对处于编程模式的设备写物理地址
    int knxWritePAByBroadcastMethod(QSerialPort *serial, unsigned char *writePAMessage, int writePAMessageLen);
    
    //计算读取处于编程模式的设备的物理地址的报文
    unsigned char *knxGetReadDevicePAByBroadcastMethod(unsigned char *readDevicePAMessage, unsigned char MCPAByteHigh, unsigned char MCPAByteLow);
    
    //获取处于编程模式的设备的物理地址
    int knxReadDevicePAByBroadcastMethod(QSerialPort *serial, unsigned char *readPAMessage, int readPAMessageLen);
    
    //计算设置设备模式的报文函数
    unsigned char* knxGetDeviceModeMessage(unsigned char* deviceModeMessage,unsigned char* sn,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,int deviceModeFlag);
    
    //设置设备模式
    int knxSetDeviceMode(QSerialPort *serial,unsigned char* setDeviceModeMessage,int setDeviceModeMessageLen);
    
    //debug打印uchar报文
    void knxDebugUcharMessage(unsigned char* ucharMessage,int ucharMessageLen);
    
    //序列号转换函数1（uchar数组转换为字符串）
    QString knxSNUcharToString(QString SNBuff,unsigned char* SNUchar);
    
    //序列号转换函数2（QString字符串转化为uchar数组）
    int knxSNQStringToUchar(unsigned char* SNUchar,QString SNBuff);
    
    //物理地址int型转换为字符串
    QString knxSetPAToString(QString PAStr,int PA);
    
    //组地址int型转换为字符串
    QString knxSetGAToString(QString GAStr,int GA);
    
    //物理地址字符串（*.*.*或者*/*/*，比如0.0.1或者0/0/1）转换为两个字节
    uchar* knxGetPATwoByte(QString PAStr,uchar* paArray);
    
    //组地址字符串（*.*.*或者*/*/*，比如0.0.1或者0/0/1）转换为两个字节
    uchar* knxGetGATwoByte(QString GAStr,uchar* gaArray);
    
    //计算建立连接和断开连接的报文
    unsigned char* knxGetConOrDisMessage(unsigned char* connectOrDisMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,int connectOrDisFlag);
    
    //建立连接和断开连接函数
    int knxConnectOrDisconnect(QSerialPort* serial,unsigned char* connectOrDisMessage,int connectOrDisMessageLen);
    
    //计算重启设备的报文
    unsigned char* knxGetRestartMessage(unsigned char* restartMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow);
    
    //重启设备函数
    int knxRestart(QSerialPort* serial,unsigned char* restartMessage,int restartMessageLen);
    
    //计算根据序列号写物理地址的报文
    unsigned char* knxGetWritePAMessage(unsigned char* writePAMessage,unsigned char* sn,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow);
    
    //根据序列号写物理地址函数
    int knxWritePAAccordingToSN(QSerialPort* serial,unsigned char* writePAMessage,int writePAMessageLen);
    
    //计算获取设备信息的报文
    unsigned char* knxGetDeviceInfoMessage(unsigned char* getDeviceInfoMessage,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,int getDeviceInfoFlag);
    
    //获取设备信息的函数
    QString knxGetDeviceInfo(QSerialPort* serial,QString deviceInfo,unsigned char* getDeviceInfoMessage,int getDeviceInfoMessageLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,int getDeviceInfoFlag);
    
    //计算获取设备模式和物理地址的报文
    unsigned char* knxGetDeviceModeAndPAMessage(unsigned char* getDeviceModeAndPAMessage,unsigned char* sn,unsigned char MCPAByteHigh,unsigned char MCPAByteLow);
    
    //获取设备模式和物理地址
    int knxGetDeviceModeAndPA(QSerialPort* serial,unsigned char* getDeviceModeAndPAMessage,int getDeviceModeAndPAMessageLen,int getDeviceModeAndPAFlag);
    
    //判断设备型号和模式
    int knxJudgeDeviceTypeAndMode(int mode,QString deviceType);
    
    //写数据函数
    int knxWriteData(QSerialPort* serial,unsigned char* message,int messageLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow);
    
    //通过标准帧发送通讯对象表、地址表、关联表数据
    int knxSendTableUseStandardFrame(QSerialPort* serial,unsigned char* tableData,int dataLen,unsigned char MCPAByteHigh,unsigned char MCPAByteLow,unsigned char devicePAByteHigh,unsigned char devicePAByteLow,unsigned short eepromAddressBegin);
};

#endif // QKNXSERIAL_H
